{ "cells": [ { "cell_type": "markdown", "metadata": { "school_cell_uuid": "353fc77e182f4061b8b4594194cd9fe8" }, "source": [ "# 4.7 피봇테이블과 그룹분석" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "215df9897d5d4571a6511331e5cee03d" }, "source": [ "## 피봇테이블" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{margin}\n", "`pivot`\n", "```" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "0e1d795bd66e4f8cab625aee76ffae39" }, "source": [ "피봇테이블(pivot table)이란 데이터 열 중에서 두 개의 열을 각각 행 인덱스, 열 인덱스로 사용하여 데이터를 조회하여 펼쳐놓은 것을 말한다.\n", "\n", "판다스는 피봇테이블을 만들기 위한 `pivot` 메서드를 제공한다. 첫번째 인수로는 행 인덱스로 사용할 열 이름, 두번째 인수로는 열 인덱스로 사용할 열 이름, 그리고 마지막으로 데이터로 사용할 열 이름을 넣는다.\n", "\n", "판다스는 지정된 두 열을 각각 행 인덱스와 열 인덱스로 바꾼 후 행 인덱스의 라벨 값이 첫번째 키의 값과 같고 열 인덱스의 라벨 값이 두번째 키의 값과 같은 데이터를 찾아서 해당 칸에 넣는다. 만약 주어진 데이터가 존재하지 않으면 해당 칸에 `NaN` 값을 넣는다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "다음 데이터는 각 도시의 연도별 인구를 나타낸 것이다." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "school_cell_uuid": "9015023ce50a4bac87830f7fa6f947a3" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
도시연도인구지역
0서울20159904312수도권
1서울20109631482수도권
2서울20059762546수도권
3부산20153448737경상권
4부산20103393191경상권
5부산20053512547경상권
6인천20152890451수도권
7인천2010263203수도권
\n", "
" ], "text/plain": [ " 도시 연도 인구 지역\n", "0 서울 2015 9904312 수도권\n", "1 서울 2010 9631482 수도권\n", "2 서울 2005 9762546 수도권\n", "3 부산 2015 3448737 경상권\n", "4 부산 2010 3393191 경상권\n", "5 부산 2005 3512547 경상권\n", "6 인천 2015 2890451 수도권\n", "7 인천 2010 263203 수도권" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = {\n", " \"도시\": [\"서울\", \"서울\", \"서울\", \"부산\", \"부산\", \"부산\", \"인천\", \"인천\"],\n", " \"연도\": [\"2015\", \"2010\", \"2005\", \"2015\", \"2010\", \"2005\", \"2015\", \"2010\"],\n", " \"인구\": [9904312, 9631482, 9762546, 3448737, 3393191, 3512547, 2890451, 263203],\n", " \"지역\": [\"수도권\", \"수도권\", \"수도권\", \"경상권\", \"경상권\", \"경상권\", \"수도권\", \"수도권\"]\n", "}\n", "columns = [\"도시\", \"연도\", \"인구\", \"지역\"]\n", "df1 = pd.DataFrame(data, columns=columns)\n", "df1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 데이터를 도시 이름이 열 인덱스가 되고 연도가 행 인덱스가 되어 행과 열 인덱스만 보면 어떤 도시의 어떤 시점의 인구를 쉽게 알 수 있도록 피봇테이블로 만들어보자. `pivot` 명령으로 사용하고 행 인덱스 인수로는 `\"도시\"`, 열 인덱스 인수로는 `\"연도\"`, 데이터 이름으로 `\"인구\"`를 입력하면 된다." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "school_cell_uuid": "09f74f677def485baca9b1be439cfe04" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
연도200520102015
도시
부산3512547.03393191.03448737.0
서울9762546.09631482.09904312.0
인천NaN263203.02890451.0
\n", "
" ], "text/plain": [ "연도 2005 2010 2015\n", "도시 \n", "부산 3512547.0 3393191.0 3448737.0\n", "서울 9762546.0 9631482.0 9904312.0\n", "인천 NaN 263203.0 2890451.0" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.pivot(\"도시\", \"연도\", \"인구\")" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "c8e3b4e96e89486f81c8537d9c63b220" }, "source": [ "이 피봇테이블의 값 3512547은 \"도시\"가 부산이고 \"연도\"가 2005년인 데이터를 \"인구\"열에서 찾은 값이다. 2005년 인천의 인구는 데이터에 없기 때문에 `NaN`으로 표시된다." ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "fbd32cc5132b4159baa243b4106c7dee" }, "source": [ " 피봇테이블은 다음과 같이 `set_index` 명령과 `unstack` 명령을 사용해서 만들 수도 있다." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "school_cell_uuid": "5d41fe936e5142d5989fcff35a59bc67" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
인구
연도200520102015
도시
부산3512547.03393191.03448737.0
서울9762546.09631482.09904312.0
인천NaN263203.02890451.0
\n", "
" ], "text/plain": [ " 인구 \n", "연도 2005 2010 2015\n", "도시 \n", "부산 3512547.0 3393191.0 3448737.0\n", "서울 9762546.0 9631482.0 9904312.0\n", "인천 NaN 263203.0 2890451.0" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.set_index([\"도시\", \"연도\"])[[\"인구\"]].unstack()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "행 인덱스나 열 인덱스를 리스트로 주는 경우에는 다중 인덱스 피봇 테이블을 생성한다. (주의: 판다스 버전 1.1 미만에서는 버그로 인해 동작하지 않는다.)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
연도200520102015
지역도시
경상권부산3512547.03393191.03448737.0
수도권서울9762546.09631482.09904312.0
인천NaN263203.02890451.0
\n", "
" ], "text/plain": [ "연도 2005 2010 2015\n", "지역 도시 \n", "경상권 부산 3512547.0 3393191.0 3448737.0\n", "수도권 서울 9762546.0 9631482.0 9904312.0\n", " 인천 NaN 263203.0 2890451.0" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.pivot([\"지역\", \"도시\"], \"연도\", \"인구\")" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "0fb65743ac624159ba7afe43bd676113" }, "source": [ "행 인덱스와 열 인덱스는 데이터를 찾는 키(key)의 역할을 한다. 따라서 키 값으로 데이터가 단 하나만 찾아져야 한다.\n", "만약 행 인덱스와 열 인덱스 조건을 만족하는 데이터가 2개 이상인 경우에는 에러가 발생한다. 예를 들어 위 데이터프레임에서 (\"지역\", \"연도\")를 키로 하면 (\"수도권\", \"2015\")에 해당하는 값이 두 개 이상이므로 다음과 같이 에러가 발생한다. " ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "school_cell_uuid": "d1256836fa7c4095b43b026eacf66f22" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ValueError: Index contains duplicate entries, cannot reshape\n" ] } ], "source": [ "try:\n", " df1.pivot(\"지역\", \"연도\", \"인구\")\n", "except ValueError as e:\n", " print(\"ValueError:\", e)" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "2344b336a7244893a6a2df8de2c6606c" }, "source": [ "## 그룹분석" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "356560bdb89f40f4a9fa8f76082acaf8" }, "source": [ "만약 키가 지정하는 조건에 맞는 데이터가 하나 이상이라서 데이터 그룹을 이루는 경우에는 그룹의 특성을 보여주는 그룹분석(group analysis)을 해야 한다.\n", "\n", "그룹분석은 피봇테이블과 달리 키에 의해서 결정되는 데이터가 여러개가 있을 경우 미리 지정한 연산을 통해 그 그룹 데이터의 대표값을 계산한다. 판다스에서는 `groupby` 메서드를 사용하여 다음처럼 그룹분석을 한다.\n", "\n", "1. 분석하고자 하는 시리즈나 데이터프레임에 `groupby` 메서드를 호출하여 그룹화를 한다.\n", "1. 그룹 객체에 대해 그룹연산을 수행한다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{margin}\n", "`groupby`\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `groupby` 메서드" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "38b951f8ebb845ee8a964dff27189560" }, "source": [ "`groupby` 메서드는 데이터를 그룹 별로 분류하는 역할을 한다. `groupby` 메서드의 인수로는 다음과 같은 값을 사용한다.\n", "\n", " * 열 또는 열의 리스트 \n", " * 행 인덱스\n", "\n", "연산 결과로 그룹 데이터를 나타내는 `GroupBy` 클래스 객체를 반환한다. 이 객체에는 그룹별로 연산을 할 수 있는 그룹연산 메서드가 있다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 그룹연산 메서드" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "4c85fc7bc5b246ec9511252e39c15846" }, "source": [ "`groupby` 결과, 즉 `GroupBy` 클래스 객체의 뒤에 붙일 수 있는 그룹연산 메서드는 다양하다. 다음은 자주 사용되는 그룹연산 메서드들이다.\n", "\n", "* `size`, `count`: 그룹 데이터의 갯수\n", "* `mean`, `median`, `min`, `max`: 그룹 데이터의 평균, 중앙값, 최소, 최대\n", "* `sum`, `prod`, `std`, `var`, `quantile` : 그룹 데이터의 합계, 곱, 표준편차, 분산, 사분위수\n", "* `first`, `last`: 그룹 데이터 중 가장 첫번째 데이터와 가장 나중 데이터\n", " \n", "이 외에도 많이 사용되는 것으로는 다음과 같은 그룹연산이 있다.\n", "\n", "* `agg`, `aggregate`\n", " * 만약 원하는 그룹연산이 없는 경우 함수를 만들고 이 함수를 `agg`에 전달한다.\n", " * 또는 여러가지 그룹연산을 동시에 하고 싶은 경우 함수 이름 문자열의 리스트를 전달한다.\n", "\n", "* `describe`\n", " * 하나의 그룹 대표값이 아니라 여러개의 값을 데이터프레임으로 구한다.\n", " \n", "* `apply`\n", " * `describe` 처럼 하나의 대표값이 아닌 데이터프레임을 출력하지만 원하는 그룹연산이 없는 경우에 사용한다.\n", " \n", "* `transform`\n", " * 그룹에 대한 대표값을 만드는 것이 아니라 그룹별 계산을 통해 데이터 자체를 변형한다." ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "7e65722c5c4d475d80f9cfbc77ffa975" }, "source": [ "예를 들어 다음과 같은 데이터가 있을 때 key1의 값(A 또는 B)에 따른 data1의 평균은 어떻게 구할까?" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "school_cell_uuid": "96d20974833c49a3aebcea54bbeb53ef" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
key1key2data1data2
0Aone110
1Atwo220
2Bone330
3Btwo440
4Aone550
\n", "
" ], "text/plain": [ " key1 key2 data1 data2\n", "0 A one 1 10\n", "1 A two 2 20\n", "2 B one 3 30\n", "3 B two 4 40\n", "4 A one 5 50" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.random.seed(0)\n", "df2 = pd.DataFrame({\n", " 'key1': ['A', 'A', 'B', 'B', 'A'],\n", " 'key2': ['one', 'two', 'one', 'two', 'one'],\n", " 'data1': [1, 2, 3, 4, 5],\n", " 'data2': [10, 20, 30, 40, 50]\n", "})\n", "df2" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "9630f592949a4ac98865787c3877fabf" }, "source": [ "`groupby` 명령을 사용하여 그룹 A와 그룹 B로 구분한 그룹 데이터를 만든다." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "groups = df2.groupby(df2.key1)\n", "groups" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 `GroupBy` 클래스 객체에는 각 그룹 데이터의 인덱스를 저장한 `groups` 속성이 있다." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'A': [0, 1, 4], 'B': [2, 3]}" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "groups.groups" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A그룹과 B그룹 데이터의 합계를 구하기 위해 `sum`이라는 그룹연산을 한다." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "school_cell_uuid": "2808b883914b41019243ae192891f057" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
data1data2
key1
A880
B770
\n", "
" ], "text/plain": [ " data1 data2\n", "key1 \n", "A 8 80\n", "B 7 70" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "groups.sum()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "f1ab01ae675d4b1b8afbc6af2b16134b" }, "source": [ "`GroupBy` 클래스 객체를 명시적으로 얻을 필요가 없다면 `groupby` 메서드와 그룹연산 메서드를 연속으로 호출한다. 다음 예제는 열 `data1`에 대해서만 그룹연산을 하는 코드이다." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "school_cell_uuid": "2808b883914b41019243ae192891f057" }, "outputs": [ { "data": { "text/plain": [ "key1\n", "A 8\n", "B 7\n", "Name: data1, dtype: int64" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2.data1.groupby(df2.key1).sum()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "데이터를 그룹으로 나눈 `GroupBy` 클래스 객체 또는 그룹분석한 결과에서 `data1`만 뽑아도 된다." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "school_cell_uuid": "cf539f8c5d5d45ef99c2bda7002efad4" }, "outputs": [ { "data": { "text/plain": [ "key1\n", "A 8\n", "B 7\n", "Name: data1, dtype: int64" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2.groupby(df2.key1)[\"data1\"].sum() # `GroupBy` 클래스 객체에서 data1만 선택하여 분석하는 경우" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "school_cell_uuid": "cba7a9ec38c746488abd779bfc2207f8" }, "outputs": [ { "data": { "text/plain": [ "key1\n", "A 8\n", "B 7\n", "Name: data1, dtype: int64" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2.groupby(df2.key1).sum()[\"data1\"] # 전체 데이터를 분석한 후 data1만 선택한 경우" ] }, { "cell_type": "markdown", "metadata": { "bootstrap": { "panel": { "class": "panel-default" } }, "school_cell_uuid": "4b5f7eb125434f9588e5fcd0e45dd6e9" }, "source": [ "````{admonition} 연습 문제 4.7.1\n", "\n", "key1의 값을 기준으로 data1의 값을 분류하여 합계를 구한 결과를 시리즈가 아닌 데이터프레임으로 구한다.\n", "````" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "33d603706a6a499083ff3758cc15bca1" }, "source": [ "이번에는 복합 키 (key1, key2) 값에 따른 data1의 합계를 구하자. \n", "분석하고자 하는 키가 복수이면 리스트를 사용한다." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "school_cell_uuid": "c360c8775f9040618f78e52811f52efc" }, "outputs": [ { "data": { "text/plain": [ "key1 key2\n", "A one 6\n", " two 2\n", "B one 3\n", " two 4\n", "Name: data1, dtype: int64" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2.data1.groupby([df2.key1, df2.key2]).sum()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "2fe61a1eaeb04a87a7122a9cdacdd566" }, "source": [ "이 결과를 `unstack` 명령으로 피봇 데이블 형태로 만들수도 있다." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "school_cell_uuid": "eaf18468cc3b4d188d18d069a2e39618" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
key2onetwo
key1
A62
B34
\n", "
" ], "text/plain": [ "key2 one two\n", "key1 \n", "A 6 2\n", "B 3 4" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2.data1.groupby([df2[\"key1\"], df2[\"key2\"]]).sum().unstack(\"key2\")" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "e41ec2708457473d8ddefac7075e55ef" }, "source": [ "그룹분석 기능을 사용하면 위의 인구 데이터로부터 지역별 합계를 구할 수도 있다." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "school_cell_uuid": "6fdfb59cac404fafba3d23d0bdbb4206" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
연도200520102015
지역
경상권351254733931913448737
수도권9762546989468512794763
\n", "
" ], "text/plain": [ "연도 2005 2010 2015\n", "지역 \n", "경상권 3512547 3393191 3448737\n", "수도권 9762546 9894685 12794763" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1[\"인구\"].groupby([df1[\"지역\"], df1[\"연도\"]]).sum().unstack(\"연도\")" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "86f05d6ec2334f4d99a5d05e774d7c96" }, "source": [ "다음 데이터는 150 송이의 붓꽃(iris)에 대해 붓꽃 종(species)별로 꽃잎길이(sepal_length), 꽃잎폭(sepal_width), 꽃잎폭(sepal_width), 꽃잎폭(sepal_width)을 측정한 데이터이다. " ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "school_cell_uuid": "c998ff1907d6438e911ea526efabcdac" }, "outputs": [], "source": [ "import seaborn as sns\n", "iris = sns.load_dataset(\"iris\")" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "a5d1177080f54869ae907b11cd0f6d42" }, "source": [ "각 붓꽃 종별로 가장 큰 값과 가장 작은 값의 비율을 구해보자. 이러한 계산을 하는 그룹연산 메서드는 없으므로 직접 만든 후 `agg` 메서드를 적용한다." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "school_cell_uuid": "8b4000bc559947159cf21e78896d9e03" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal_lengthsepal_widthpetal_lengthpetal_width
species
setosa1.3488371.9130431.9000006.000000
versicolor1.4285711.7000001.7000001.800000
virginica1.6122451.7272731.5333331.785714
\n", "
" ], "text/plain": [ " sepal_length sepal_width petal_length petal_width\n", "species \n", "setosa 1.348837 1.913043 1.900000 6.000000\n", "versicolor 1.428571 1.700000 1.700000 1.800000\n", "virginica 1.612245 1.727273 1.533333 1.785714" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def peak_to_peak_ratio(x):\n", " return x.max() / x.min()\n", "\n", "iris.groupby(iris.species).agg(peak_to_peak_ratio)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{margin}\n", "`describe`\n", "```" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "8b83fb8ed916451c8e1db3d64236dffa" }, "source": [ "`describe` 메서드를 사용하면 다양한 기술 통계(descriptive statistics)값을 한 번에 구한다. 그룹별로 하나의 스칼라 값이 아니라 하나의 데이터프레임이 생성된다는 점에 주의하라." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "school_cell_uuid": "2b5f4c36cbac43628e0e43f3140a6165" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
speciessetosaversicolorvirginica
sepal_lengthcount50.00000050.00000050.000000
mean5.0060005.9360006.588000
std0.3524900.5161710.635880
min4.3000004.9000004.900000
25%4.8000005.6000006.225000
50%5.0000005.9000006.500000
75%5.2000006.3000006.900000
max5.8000007.0000007.900000
sepal_widthcount50.00000050.00000050.000000
mean3.4280002.7700002.974000
std0.3790640.3137980.322497
min2.3000002.0000002.200000
25%3.2000002.5250002.800000
50%3.4000002.8000003.000000
75%3.6750003.0000003.175000
max4.4000003.4000003.800000
petal_lengthcount50.00000050.00000050.000000
mean1.4620004.2600005.552000
std0.1736640.4699110.551895
min1.0000003.0000004.500000
25%1.4000004.0000005.100000
50%1.5000004.3500005.550000
75%1.5750004.6000005.875000
max1.9000005.1000006.900000
petal_widthcount50.00000050.00000050.000000
mean0.2460001.3260002.026000
std0.1053860.1977530.274650
min0.1000001.0000001.400000
25%0.2000001.2000001.800000
50%0.2000001.3000002.000000
75%0.3000001.5000002.300000
max0.6000001.8000002.500000
\n", "
" ], "text/plain": [ "species setosa versicolor virginica\n", "sepal_length count 50.000000 50.000000 50.000000\n", " mean 5.006000 5.936000 6.588000\n", " std 0.352490 0.516171 0.635880\n", " min 4.300000 4.900000 4.900000\n", " 25% 4.800000 5.600000 6.225000\n", " 50% 5.000000 5.900000 6.500000\n", " 75% 5.200000 6.300000 6.900000\n", " max 5.800000 7.000000 7.900000\n", "sepal_width count 50.000000 50.000000 50.000000\n", " mean 3.428000 2.770000 2.974000\n", " std 0.379064 0.313798 0.322497\n", " min 2.300000 2.000000 2.200000\n", " 25% 3.200000 2.525000 2.800000\n", " 50% 3.400000 2.800000 3.000000\n", " 75% 3.675000 3.000000 3.175000\n", " max 4.400000 3.400000 3.800000\n", "petal_length count 50.000000 50.000000 50.000000\n", " mean 1.462000 4.260000 5.552000\n", " std 0.173664 0.469911 0.551895\n", " min 1.000000 3.000000 4.500000\n", " 25% 1.400000 4.000000 5.100000\n", " 50% 1.500000 4.350000 5.550000\n", " 75% 1.575000 4.600000 5.875000\n", " max 1.900000 5.100000 6.900000\n", "petal_width count 50.000000 50.000000 50.000000\n", " mean 0.246000 1.326000 2.026000\n", " std 0.105386 0.197753 0.274650\n", " min 0.100000 1.000000 1.400000\n", " 25% 0.200000 1.200000 1.800000\n", " 50% 0.200000 1.300000 2.000000\n", " 75% 0.300000 1.500000 2.300000\n", " max 0.600000 1.800000 2.500000" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iris.groupby(iris.species).describe().T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{margin}\n", "`apply`\n", "```" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "584da999b9894543b64e5e21c108baa7" }, "source": [ "`apply` 메서드를 사용하면 `describe` 메서드처럼 하나의 그룹에 대해 하나의 대표값(스칼라 값)을 구하는 게 아니라 데이터프레임을 만들 수 있다. 예를 들어 다음처럼 각 붓꽃 종별로 가장 꽃잎 길이(petal length)가 큰 3개의 데이터를 뽑아낼 수도 있다." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "school_cell_uuid": "0643604b8876431eb5f7b1d85f722fc3" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepal_lengthsepal_widthpetal_lengthpetal_widthspecies
species
setosa244.83.41.90.2setosa
445.13.81.90.4setosa
235.13.31.70.5setosa
versicolor836.02.75.11.6versicolor
776.73.05.01.7versicolor
726.32.54.91.5versicolor
virginica1187.72.66.92.3virginica
1177.73.86.72.2virginica
1227.72.86.72.0virginica
\n", "
" ], "text/plain": [ " sepal_length sepal_width petal_length petal_width \\\n", "species \n", "setosa 24 4.8 3.4 1.9 0.2 \n", " 44 5.1 3.8 1.9 0.4 \n", " 23 5.1 3.3 1.7 0.5 \n", "versicolor 83 6.0 2.7 5.1 1.6 \n", " 77 6.7 3.0 5.0 1.7 \n", " 72 6.3 2.5 4.9 1.5 \n", "virginica 118 7.7 2.6 6.9 2.3 \n", " 117 7.7 3.8 6.7 2.2 \n", " 122 7.7 2.8 6.7 2.0 \n", "\n", " species \n", "species \n", "setosa 24 setosa \n", " 44 setosa \n", " 23 setosa \n", "versicolor 83 versicolor \n", " 77 versicolor \n", " 72 versicolor \n", "virginica 118 virginica \n", " 117 virginica \n", " 122 virginica " ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def top3_petal_length(df):\n", " return df.sort_values(by=\"petal_length\", ascending=False)[:3]\n", "\n", "iris.groupby(iris.species).apply(top3_petal_length)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{margin}\n", "`transform`\n", "```" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "237526cb959b4ae6a45b0115f702e21e" }, "source": [ "`transform` 메서드는 그룹별 대표값을 만드는 것이 아니라 그룹별 계산을 통해 데이터프레임 자체를 변화시킨다. 따라서 만들어진 데이터프레임의 크기는 원래 데이터프레임과 같다. 예를 들어 다음처럼 각 붓꽃 꽃잎길이가 해당 종 내에서 대/중/소 어느 것에 해당되는지에 대한 데이터프레임을 만들 수도 있다." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "school_cell_uuid": "de641b5d681545c5be5ce050eec6b6f1" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
petal_lengthpetal_length_class
1405.6
1415.1
1425.1
1435.9
1445.7
1455.2
1465.0
1475.2
1485.4
1495.1
\n", "
" ], "text/plain": [ " petal_length petal_length_class\n", "140 5.6 중\n", "141 5.1 소\n", "142 5.1 소\n", "143 5.9 대\n", "144 5.7 중\n", "145 5.2 소\n", "146 5.0 소\n", "147 5.2 소\n", "148 5.4 중\n", "149 5.1 소" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def q3cut(s):\n", " return pd.qcut(s, 3, labels=[\"소\", \"중\", \"대\"]).astype(str)\n", "\n", "\n", "iris[\"petal_length_class\"] = iris.groupby(iris.species).petal_length.transform(q3cut)\n", "iris[[\"petal_length\", \"petal_length_class\"]].tail(10)" ] }, { "cell_type": "markdown", "metadata": { "bootstrap": { "panel": { "class": "panel-default" } }, "school_cell_uuid": "4b5f7eb125434f9588e5fcd0e45dd6e9" }, "source": [ "````{admonition} 연습 문제 4.7.2\n", "\n", "붓꽃(iris) 데이터에서 붓꽃 종(species)별로 꽃잎길이(sepal_length), 꽃잎폭(sepal_width) 등의 평균을 구하라.\n", "만약 붓꽃 종(species)이 표시되지 않았을 때 이 수치들을 이용하여 붓꽃 종을 찾아낼 수 있을지 생각하라.\n", "````" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "bede55f288dc48c3a6f3148b34bf5339" }, "source": [ "## `pivot_table`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{margin}\n", "`pivot_table`\n", "```" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "849bac0a30634b639c228cce976dc084" }, "source": [ "Pandas는 `pivot` 명령과 `groupby` 명령의 중간 성격을 가지는 `pivot_table` 명령도 제공한다.\n", "\n", "`pivot_table` 명령은 `groupby` 명령처럼 그룹분석을 하지만 최종적으로는 `pivot` 명령처럼 피봇테이블을 만든다. 즉 `groupby` 명령의 결과에 `unstack`을 자동 적용하여 2차원적인 형태로 변형한다. 사용 방법은 다음과 같다.\n", "\n", "* `pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, margins_name='All')`\n", " * `data`: 분석할 데이터프레임 (메서드일 때는 필요하지 않음)\n", " * `values`: 분석할 데이터프레임에서 분석할 열\n", " * `index`: 행 인덱스로 들어갈 키 열 또는 키 열의 리스트\n", " * `columns`: 열 인덱스로 들어갈 키 열 또는 키 열의 리스트\n", " * `aggfunc`: 분석 메서드\n", " * `fill_value`: NaN 대체 값\n", " * `margins`: 모든 데이터를 분석한 결과를 오른쪽과 아래에 붙일지 여부\n", " * `margins_name`: 마진 열(행)의 이름\n", " \n", "만약 조건에 따른 데이터가 유일하게 선택되지 않으면 그룹연산을 하며 이 때 `aggfunc` 인수로 정의된 함수를 수행하여 대표값을 계산한다.\n", "\n", "`pivot_table`를 메서드로 사용할 때는 객체 자체가 데이터가 되므로 `data` 인수가 필요하지 않다." ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "9da1e1d0821949028ebbc11f53e4ca97" }, "source": [ "예를 들어 위에서 만들었던 피봇테이블은 `pivot_table` 명령으로 다음과 같이 만들 수도 있다. 인수의 순서에 주의하라." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "school_cell_uuid": "08b76b7daf4c4aabb0cbaa77a66f4e5f" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
연도200520102015
도시
부산3512547.03393191.03448737.0
서울9762546.09631482.09904312.0
인천NaN263203.02890451.0
\n", "
" ], "text/plain": [ "연도 2005 2010 2015\n", "도시 \n", "부산 3512547.0 3393191.0 3448737.0\n", "서울 9762546.0 9631482.0 9904312.0\n", "인천 NaN 263203.0 2890451.0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.pivot_table(\"인구\", \"도시\", \"연도\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`margins=True` 인수를 주면 `aggfunc`로 주어진 분석 방법을 해당 열의 모든 데이터, 해당 행의 모든 데이터 그리고 전체 데이터에 대해 적용한 결과를 같이 보여준다. `aggfunc`가 주어지지 않았으면 평균을 계산한다." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "school_cell_uuid": "484dafe7764e48f8b993790c629b1eb9" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
연도200520102015합계
도시
부산3512547.03393191.03448737.03.451492e+06
서울9762546.09631482.09904312.09.766113e+06
인천NaN263203.02890451.01.576827e+06
합계6637546.54429292.05414500.05.350809e+06
\n", "
" ], "text/plain": [ "연도 2005 2010 2015 합계\n", "도시 \n", "부산 3512547.0 3393191.0 3448737.0 3.451492e+06\n", "서울 9762546.0 9631482.0 9904312.0 9.766113e+06\n", "인천 NaN 263203.0 2890451.0 1.576827e+06\n", "합계 6637546.5 4429292.0 5414500.0 5.350809e+06" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.pivot_table(\"인구\", \"도시\", \"연도\", margins=True, margins_name=\"합계\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 결과에서 가장 오른쪽 합계 열의 첫번째 값 3451492은 모든 부산 인구 데이터의 평균, 두번째 값 9766113은 모든 서울 인구 데이터의 평균이다. 가장 아래의 합계 행의 첫번째 값은 2005년 데이터의 평균값, 두번째 값은 2010년 데이터의 평균값이다. 가장 오른쪽 아래의 값 5350809는 전체 데이터의 평균값이다. 다음 계산을 통해 이를 확인할 수 있다." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5350808.625" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1[\"인구\"].mean()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "f8c58621cd594ec3a912c80712aaa0e3" }, "source": [ "행 인덱스나 열 인덱스에 리스트를 넣으면 다중 인덱스 테이블을 만든다." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "school_cell_uuid": "c172b1deec514208b34b4477b6c8c930" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
인구
연도도시
2005부산3512547
서울9762546
2010부산3393191
서울9631482
인천263203
2015부산3448737
서울9904312
인천2890451
\n", "
" ], "text/plain": [ " 인구\n", "연도 도시 \n", "2005 부산 3512547\n", " 서울 9762546\n", "2010 부산 3393191\n", " 서울 9631482\n", " 인천 263203\n", "2015 부산 3448737\n", " 서울 9904312\n", " 인천 2890451" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.pivot_table(\"인구\", index=[\"연도\", \"도시\"])" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "317ad7281cef43ae98fc2351521798a7" }, "source": [ "식당에서 식사 후 내는 팁(tip)과 관련된 데이터를 이용하여 좀더 구체적으로 그룹분석 방법을 살펴본다. 우선 Seaborn 패키지에 설치된 샘플 데이터를 로드한다. 이 데이터프레임에서 각각의 컬럼은 다음을 뜻한다.\n", "\n", "* total_bill: 식사대금\n", "* tip: 팁\n", "* sex: 성별\n", "* smoker: 흡연/금연 여부\n", "* day: 요일\n", "* time: 시간\n", "* size: 인원" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "school_cell_uuid": "cc2f62fa6d454d99a75bb1e98d62ccb6" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
total_billtipsexsmokerdaytimesize
23929.035.92MaleNoSatDinner3
24027.182.00FemaleYesSatDinner2
24122.672.00MaleYesSatDinner2
24217.821.75MaleNoSatDinner2
24318.783.00FemaleNoThurDinner2
\n", "
" ], "text/plain": [ " total_bill tip sex smoker day time size\n", "239 29.03 5.92 Male No Sat Dinner 3\n", "240 27.18 2.00 Female Yes Sat Dinner 2\n", "241 22.67 2.00 Male Yes Sat Dinner 2\n", "242 17.82 1.75 Male No Sat Dinner 2\n", "243 18.78 3.00 Female No Thur Dinner 2" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips = sns.load_dataset(\"tips\")\n", "tips.tail()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "82ce76a6507244869b36fdb5a3676459" }, "source": [ "분석의 목표는 식사 대금 대비 팁의 비율이 어떤 경우에 가장 높아지지는 찾는 것이다. 우선 식사대금와 팁의 비율을 나타내는 `tip_pct`를 추가하자." ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "school_cell_uuid": "e1cb3432993742789b1fa635862559c8" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
total_billtipsexsmokerdaytimesizetip_pct
23929.035.92MaleNoSatDinner30.203927
24027.182.00FemaleYesSatDinner20.073584
24122.672.00MaleYesSatDinner20.088222
24217.821.75MaleNoSatDinner20.098204
24318.783.00FemaleNoThurDinner20.159744
\n", "
" ], "text/plain": [ " total_bill tip sex smoker day time size tip_pct\n", "239 29.03 5.92 Male No Sat Dinner 3 0.203927\n", "240 27.18 2.00 Female Yes Sat Dinner 2 0.073584\n", "241 22.67 2.00 Male Yes Sat Dinner 2 0.088222\n", "242 17.82 1.75 Male No Sat Dinner 2 0.098204\n", "243 18.78 3.00 Female No Thur Dinner 2 0.159744" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips['tip_pct'] = tips['tip'] / tips['total_bill']\n", "tips.tail()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "93213c7480b04e509359b99064e4ca51" }, "source": [ "다음으로 각 열의 데이터에 대해 간단히 분포를 알아본다." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "school_cell_uuid": "7b4c0a8e1f21419aa260626237335939" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
total_billtipsizetip_pct
count244.000000244.000000244.000000244.000000
mean19.7859432.9982792.5696720.160803
std8.9024121.3836380.9511000.061072
min3.0700001.0000001.0000000.035638
25%13.3475002.0000002.0000000.129127
50%17.7950002.9000002.0000000.154770
75%24.1275003.5625003.0000000.191475
max50.81000010.0000006.0000000.710345
\n", "
" ], "text/plain": [ " total_bill tip size tip_pct\n", "count 244.000000 244.000000 244.000000 244.000000\n", "mean 19.785943 2.998279 2.569672 0.160803\n", "std 8.902412 1.383638 0.951100 0.061072\n", "min 3.070000 1.000000 1.000000 0.035638\n", "25% 13.347500 2.000000 2.000000 0.129127\n", "50% 17.795000 2.900000 2.000000 0.154770\n", "75% 24.127500 3.562500 3.000000 0.191475\n", "max 50.810000 10.000000 6.000000 0.710345" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.describe()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "c0a99b12bc1f4787b51f049b8f718b1e" }, "source": [ "우선 성별로 나누어 데이터 갯수를 세어본다." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "school_cell_uuid": "473bbbfdbc654cd49cded74d53ec132f" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
total_billtipsmokerdaytimesizetip_pct
sex
Male157157157157157157157
Female87878787878787
\n", "
" ], "text/plain": [ " total_bill tip smoker day time size tip_pct\n", "sex \n", "Male 157 157 157 157 157 157 157\n", "Female 87 87 87 87 87 87 87" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby(\"sex\").count()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "2f1574c4c7184b58af083698093bb126" }, "source": [ "데이터 갯수의 경우 NaN 데이터가 없다면 모두 같은 값이 나올 것이다. 이 때는 `size` 명령을 사용하면 더 간단히 표시된다. `size` 명령은 NaN이 있어도 상관하지 않는다." ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "school_cell_uuid": "00edc90849654f81acddfd414ffd614e" }, "outputs": [ { "data": { "text/plain": [ "sex\n", "Male 157\n", "Female 87\n", "dtype: int64" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby(\"sex\").size()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "6bf15861c8594a1d80507469741e2eeb" }, "source": [ "이번에는 성별과 흡연유무로 나누어 데이터의 갯수를 알아본다." ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "school_cell_uuid": "51bda88bc0ed402185cf290fdbd5dc47" }, "outputs": [ { "data": { "text/plain": [ "sex smoker\n", "Male Yes 60\n", " No 97\n", "Female Yes 33\n", " No 54\n", "dtype: int64" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby([\"sex\", \"smoker\"]).size()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "347fcac8e82b44abb48018afb58a490a" }, "source": [ "좀 더 보기 좋도록 피봇 데이블 형태로 바꿀 수도 있다." ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "school_cell_uuid": "85e29281c1c34bb0a12e575dbf7412cc" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
smokerYesNoAll
sex
Male6097157
Female335487
All93151244
\n", "
" ], "text/plain": [ "smoker Yes No All\n", "sex \n", "Male 60 97 157\n", "Female 33 54 87\n", "All 93 151 244" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.pivot_table(\"tip_pct\", \"sex\", \"smoker\", aggfunc=\"count\", margins=True)" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "82d3d3d82d0e436a8e11bf4cf85f7fe2" }, "source": [ "이제 성별과 흡연 여부에 따른 평균 팁 비율을 살펴본다." ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "school_cell_uuid": "04336fd393c544bc91a397754b293b64" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip_pct
sex
Male0.157651
Female0.166491
\n", "
" ], "text/plain": [ " tip_pct\n", "sex \n", "Male 0.157651\n", "Female 0.166491" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby(\"sex\")[[\"tip_pct\"]].mean()" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "school_cell_uuid": "2a280666382c40f5a87efe9c0520d2f7" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip_pct
smoker
Yes0.163196
No0.159328
\n", "
" ], "text/plain": [ " tip_pct\n", "smoker \n", "Yes 0.163196\n", "No 0.159328" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby(\"smoker\")[[\"tip_pct\"]].mean()" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "e37dfbf27c5c4da081fce3fba6c3591d" }, "source": [ "`pivot_table` 명령을 사용할 수도 있다." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "school_cell_uuid": "0156dd9421664fb08bf8339845ff9271" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip_pct
sex
Male0.157651
Female0.166491
\n", "
" ], "text/plain": [ " tip_pct\n", "sex \n", "Male 0.157651\n", "Female 0.166491" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.pivot_table(\"tip_pct\", \"sex\")" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "school_cell_uuid": "0156dd9421664fb08bf8339845ff9271" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip_pct
sexsmoker
MaleYes0.152771
No0.160669
FemaleYes0.182150
No0.156921
\n", "
" ], "text/plain": [ " tip_pct\n", "sex smoker \n", "Male Yes 0.152771\n", " No 0.160669\n", "Female Yes 0.182150\n", " No 0.156921" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.pivot_table(\"tip_pct\", [\"sex\", \"smoker\"])" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "school_cell_uuid": "51bda88bc0ed402185cf290fdbd5dc47" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
smokerYesNo
sex
Male0.1527710.160669
Female0.1821500.156921
\n", "
" ], "text/plain": [ "smoker Yes No\n", "sex \n", "Male 0.152771 0.160669\n", "Female 0.182150 0.156921" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.pivot_table(\"tip_pct\", \"sex\", \"smoker\")" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "1ab65f483a7b4186b34fe6111e34e7a5" }, "source": [ "여성 혹은 흡연자의 팁 비율이 높은 것을 볼 수 있다. 하지만 이 데이터에는 평균을 제외한 분산(variance) 등의 다른 통계값이 없으므로 `describe` 명령으로 여러가지 통계값을 한 번에 알아본다." ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "school_cell_uuid": "ad7c25500b804bc89c3621ff84a1358c" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip_pct
countmeanstdmin25%50%75%max
sex
Male157.00.1576510.0647780.0356380.1213890.1534920.1862400.710345
Female87.00.1664910.0536320.0564330.1404160.1555810.1942660.416667
\n", "
" ], "text/plain": [ " tip_pct \\\n", " count mean std min 25% 50% 75% \n", "sex \n", "Male 157.0 0.157651 0.064778 0.035638 0.121389 0.153492 0.186240 \n", "Female 87.0 0.166491 0.053632 0.056433 0.140416 0.155581 0.194266 \n", "\n", " \n", " max \n", "sex \n", "Male 0.710345 \n", "Female 0.416667 " ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby(\"sex\")[[\"tip_pct\"]].describe()" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "school_cell_uuid": "ad7c25500b804bc89c3621ff84a1358c" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip_pct
countmeanstdmin25%50%75%max
smoker
Yes93.00.1631960.0851190.0356380.1067710.1538460.1950590.710345
No151.00.1593280.0399100.0567970.1369060.1556250.1850140.291990
\n", "
" ], "text/plain": [ " tip_pct \\\n", " count mean std min 25% 50% 75% \n", "smoker \n", "Yes 93.0 0.163196 0.085119 0.035638 0.106771 0.153846 0.195059 \n", "No 151.0 0.159328 0.039910 0.056797 0.136906 0.155625 0.185014 \n", "\n", " \n", " max \n", "smoker \n", "Yes 0.710345 \n", "No 0.291990 " ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby(\"smoker\")[[\"tip_pct\"]].describe()" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "school_cell_uuid": "ad7c25500b804bc89c3621ff84a1358c" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip_pct
countmeanstdmin25%50%75%max
sexsmoker
MaleYes60.00.1527710.0905880.0356380.1018450.1410150.1916970.710345
No97.00.1606690.0418490.0718040.1318100.1576040.1862200.291990
FemaleYes33.00.1821500.0715950.0564330.1524390.1739130.1982160.416667
No54.00.1569210.0364210.0567970.1397080.1496910.1816300.252672
\n", "
" ], "text/plain": [ " tip_pct \\\n", " count mean std min 25% 50% \n", "sex smoker \n", "Male Yes 60.0 0.152771 0.090588 0.035638 0.101845 0.141015 \n", " No 97.0 0.160669 0.041849 0.071804 0.131810 0.157604 \n", "Female Yes 33.0 0.182150 0.071595 0.056433 0.152439 0.173913 \n", " No 54.0 0.156921 0.036421 0.056797 0.139708 0.149691 \n", "\n", " \n", " 75% max \n", "sex smoker \n", "Male Yes 0.191697 0.710345 \n", " No 0.186220 0.291990 \n", "Female Yes 0.198216 0.416667 \n", " No 0.181630 0.252672 " ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby([\"sex\", \"smoker\"])[[\"tip_pct\"]].describe()" ] }, { "cell_type": "markdown", "metadata": { "bootstrap": { "panel": { "class": "panel-default" } }, "school_cell_uuid": "4b5f7eb125434f9588e5fcd0e45dd6e9" }, "source": [ "```{admonition} 연습 문제 4.7.3\n", "\n", "1. 팁의 비율이 요일과 점심/저녁 여부, 인원수에 어떤 영향을 받는지 살펴본다.\n", "2. 어떤 요인이 가장 크게 작용하는지 판단할 수 있는 방법이 있는가?\n", "````\n" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "84a69283ef6a4ec3914596f5875c050a" }, "source": [ "이번에는 각 그룹에서 가장 많은 팁과 가장 적은 팁의 차이를 알아보자. 이 계산을 해 줄 수 있는 그룹연산 함수가 없으므로 함수를 직접 만들고 `agg` 메서드를 사용한다." ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "school_cell_uuid": "cf52875b459640fda0a098a3de31174d" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip
sexsmoker
MaleYes9.00
No7.75
FemaleYes5.50
No4.20
\n", "
" ], "text/plain": [ " tip\n", "sex smoker \n", "Male Yes 9.00\n", " No 7.75\n", "Female Yes 5.50\n", " No 4.20" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def peak_to_peak(x):\n", " return x.max() - x.min()\n", "\n", "\n", "tips.groupby([\"sex\", \"smoker\"])[[\"tip\"]].agg(peak_to_peak)" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "462b6f2e170e44d8aeeceb44d4840103" }, "source": [ "만약 여러가지 그룹연산을 동시에 하고 싶다면 다음과 같이 리스트를 이용한다." ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "school_cell_uuid": "72767b4e40c7435b9b59e02b128cf3ad" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
total_bill
meanpeak_to_peak
sexsmoker
MaleYes22.28450043.56
No19.79123740.82
FemaleYes17.97787941.23
No18.10518528.58
\n", "
" ], "text/plain": [ " total_bill \n", " mean peak_to_peak\n", "sex smoker \n", "Male Yes 22.284500 43.56\n", " No 19.791237 40.82\n", "Female Yes 17.977879 41.23\n", " No 18.105185 28.58" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby([\"sex\", \"smoker\"]).agg([\"mean\", peak_to_peak])[[\"total_bill\"]]" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "e53d8189b7204a18bba001c96fd21d46" }, "source": [ "만약 데이터 열마다 다른 연산을 하고 싶다면 열 라벨과 연산 이름(또는 함수)를 딕셔너리로 넣는다." ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "school_cell_uuid": "d5fc79aac62c492cb97ded5e24cdee67" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tip_pcttotal_bill
sexsmoker
MaleYes0.15277143.56
No0.16066940.82
FemaleYes0.18215041.23
No0.15692128.58
\n", "
" ], "text/plain": [ " tip_pct total_bill\n", "sex smoker \n", "Male Yes 0.152771 43.56\n", " No 0.160669 40.82\n", "Female Yes 0.182150 41.23\n", " No 0.156921 28.58" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.groupby([\"sex\", \"smoker\"]).agg(\n", " {'tip_pct': 'mean', 'total_bill': peak_to_peak})" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "843a5523c58a40c9b61cc567153eb6ad" }, "source": [ "다음은 `pivot_table` 명령으로 더 복잡한 분석을 한 예이다." ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "school_cell_uuid": "1a47c3400cfb4fa5a21510a9da3cdddb" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sizetip_pct
smokerYesNoYesNo
sexday
MaleThur2.3000002.5000000.1644170.165706
Fri2.1250002.0000000.1447300.138005
Sat2.6296302.6562500.1390670.162132
Sun2.6000002.8837210.1739640.158291
FemaleThur2.4285712.4800000.1630730.155971
Fri2.0000002.5000000.2091290.165296
Sat2.2000002.3076920.1638170.147993
Sun2.5000003.0714290.2370750.165710
\n", "
" ], "text/plain": [ " size tip_pct \n", "smoker Yes No Yes No\n", "sex day \n", "Male Thur 2.300000 2.500000 0.164417 0.165706\n", " Fri 2.125000 2.000000 0.144730 0.138005\n", " Sat 2.629630 2.656250 0.139067 0.162132\n", " Sun 2.600000 2.883721 0.173964 0.158291\n", "Female Thur 2.428571 2.480000 0.163073 0.155971\n", " Fri 2.000000 2.500000 0.209129 0.165296\n", " Sat 2.200000 2.307692 0.163817 0.147993\n", " Sun 2.500000 3.071429 0.237075 0.165710" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.pivot_table(['tip_pct', 'size'], ['sex', 'day'], 'smoker')" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "school_cell_uuid": "6c586414bdf04cee8ff35255776fc778" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
dayThurFriSatSun
timesexsmoker
LunchMaleYes23500
No50000
FemaleYes17600
No60300
DinnerMaleYes0127139
No0485124
FemaleYes083310
No223043
\n", "
" ], "text/plain": [ "day Thur Fri Sat Sun\n", "time sex smoker \n", "Lunch Male Yes 23 5 0 0\n", " No 50 0 0 0\n", " Female Yes 17 6 0 0\n", " No 60 3 0 0\n", "Dinner Male Yes 0 12 71 39\n", " No 0 4 85 124\n", " Female Yes 0 8 33 10\n", " No 2 2 30 43" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tips.pivot_table('size', ['time', 'sex', 'smoker'], 'day',\n", " aggfunc='sum', fill_value=0)" ] }, { "cell_type": "markdown", "metadata": { "bootstrap": { "panel": { "class": "panel-default" } }, "school_cell_uuid": "4b5f7eb125434f9588e5fcd0e45dd6e9" }, "source": [ "````{admonition} 연습 문제 4.7.4\n", "\n", "타이타닉 승객 데이터를 이용하여 다음 분석을 실시하라. 데이터는 다음과 같이 받을 수 있다.\n", "\n", "```\n", "titanic = sns.load_dataset(\"titanic\")\n", "```\n", "\n", "1. `qcut` 명령으로 세 개의 나이 그룹을 만든다.\n", "2. 성별, 선실, 나이 그룹에 의한 생존율을 데이터프레임으로 계산한다. \n", "행에는 성별 및 나이 그룹에 대한 다중 인덱스를 사용하고 열에는 선실 인덱스를 사용한다.\n", "생존률은 해당 그룹의 생존 인원수를 전체 인원수로 나눈 값이다.\n", "3. 성별 및 선실에 의한 생존율을 피봇 데이터 형태로 만든다.\n", "````\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Edit Metadata", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 4 }